package com.emeraldparser.symbol;

import com.google.common.base.Objects;
import com.google.common.base.Preconditions;

public class Symbol<T> {

	private final SymbolClass symbolClass;
	private final T semanticValue;
	private final transient int hashCode;

	public Symbol(SymbolClass symbolClass, T semanticValue) {
		this.symbolClass = Preconditions.checkNotNull(symbolClass, "Symbol class must not be null");
		this.semanticValue = semanticValue;
		this.hashCode = Objects.hashCode(symbolClass, semanticValue);
	}

	public static <T> Symbol<T> create(SymbolClass symbolClass, T semanticValue) {
		return new Symbol<T>(symbolClass, semanticValue);
	}

	public final SymbolClass getSymbolClass() {
		return symbolClass;
	}

	public final T getSemanticValue() {
		return semanticValue;
	}

	@Override
	public String toString() {
		return semanticValue + "(" + symbolClass + ")";
	}

	@Override
	public int hashCode() {
		return hashCode;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		
		if (obj == null) {
			return false;
		}
		
		if (getClass() != obj.getClass()) {
			return false;
		}
		
		Symbol<?> other = (Symbol<?>) obj;
		
		return Objects.equal(symbolClass, other.symbolClass)
		    && Objects.equal(semanticValue, other.semanticValue);
	}

}
